package be.rivendale.material;

import org.junit.Test;

import static be.rivendale.mathematics.MathematicalAssert.assertColorEquals;
import static org.junit.Assert.*;

public class ColorTest {
    @Test
    public void constructorSetsAllColorComponents() throws Exception {
        Color color = new Color(0.5, 0.75, 1);
        assertColorEquals(new Color(0.5, 0.75, 1), color);
    }

    @Test(expected = IllegalArgumentException.class)
    public void constructorThrowsIllegalArgumentExceptionWhenRedValueIsOutOfRange() throws Exception {
        new Color(-0.1, 0, 0);
    }

    @Test(expected = IllegalArgumentException.class)
    public void constructorThrowsIllegalArgumentExceptionWhenGreenValueIsOutOfRange() throws Exception {
        new Color(0, 1.1, 0);
    }

    @Test(expected = IllegalArgumentException.class)
    public void constructorThrowsIllegalArgumentExceptionWhenBlueValueIsOutOfRange() throws Exception {
        new Color(0, 0, -0.1);
    }

    @Test
    public void constantForRedReturnsFullRedColor() throws Exception {
        assertColorEquals(new Color(1, 0, 0), Color.RED);
    }

    @Test
    public void constantForGreenReturnsFullGreenColor() throws Exception {
        assertColorEquals(new Color(0, 1, 0), Color.GREEN);
    }

    @Test
    public void constantForMagentaReturnsMagentaColor() throws Exception {
        assertColorEquals(new Color(1, 0, 1), Color.MAGENTA);
    }

    @Test
    public void constantForCyanReturnsFullCyanColor() throws Exception {
        assertColorEquals(new Color(0, 1, 1), Color.CYAN);
    }

    @Test
    public void constantForBlueReturnsFullBlueColor() throws Exception {
        assertColorEquals(new Color(0, 0, 1), Color.BLUE);
    }

    @Test
    public void constantForBlackReturnsFullBlackColor() throws Exception {
        assertColorEquals(new Color(0, 0, 0), Color.BLACK);
    }

    @Test
    public void constantForWhiteReturnsFullWhiteColor() throws Exception {
        assertColorEquals(new Color(1, 1, 1), Color.WHITE);
    }

    @Test
    public void constantForYellowReturnsFullYellowColor() {
        assertColorEquals(new Color(1, 1, 0), Color.YELLOW);
    }

    @Test
    public void equalsReturnsTrueIfBothColorsHaveTheSameColorComponents() throws Exception {
        assertTrue(new Color(0.5, 0.6, 0.7).equals(new Color(0.5, 0.6, 0.7)));
    }

    @Test
    public void equalsReturnsFalseIfBothColorsDoNotHaveTheSameColorComponents() throws Exception {
        assertFalse(new Color(0.5, 0.6, 0.7).equals(new Color(0.5, 0.61, 0.7)));
    }

    @Test
    public void toArrayReturnsIntArrayOf8BitColorComponents() throws Exception {
        assertArrayEquals(new int[] {64, 128, 191}, new Color(0.25, 0.5, 0.75).toArray());
    }

	@Test
    public void toArrayRoundsTheValuesUpIfTheFractionIsAboveZeroPointFive() throws Exception {
		assertArrayEquals(new int[] {64, 64, 64}, new Color(0.25, 0.25, 0.25).toArray());
    }

	@Test
    public void toArrayRoundsTheValuesDownIfTheFractionIsBelowZeroPointFive() throws Exception {
		assertArrayEquals(new int[] {191, 191, 191}, new Color(0.75, 0.75, 0.75).toArray());
    }

    @Test
    public void multiplyWithColorReturnsNewColorWithMultiplicationOfEachColorComponent() throws Exception {
        Color color = new Color(0.25, 0.5, 0.75).multiply(new Color(0.2, 0.3, 0.4));
        assertColorEquals(new Color(0.05, 0.15, 0.3), color);
    }

    @Test
    public void multiplyWithColorLeavesThisColorUnchanged() throws Exception {
        Color color = new Color(0.25, 0.5, 0.75);
        color.multiply(new Color(0.2, 0.3, 0.4));
        assertColorEquals(new Color(0.25, 0.5, 0.75), color);
    }

    @Test
    public void multiplyWithColorLeavesParameterColorUnchanged() throws Exception {
        Color color = new Color(0.25, 0.5, 0.75);
        new Color(0.2, 0.3, 0.4).multiply(color);
        assertColorEquals(new Color(0.25, 0.5, 0.75), color);
    }

    @Test(expected = IllegalArgumentException.class)
    public void multiplyWithColorThrowsIllegalArgumentExceptionWhenParameterIsNull() throws Exception {
        Color.RED.multiply(null);
    }

    @Test
    public void multiplyWithScalarReturnsNewColorWithMiltiplicationOfEachColorComponent() throws Exception {
        Color color = new Color(0.5, 0.5, 0.5).multiply(new Color(0.4, 0.5, 0.6));
        assertColorEquals(color, new Color(0.2, 0.25, 0.3));
    }

    @Test
    public void multiplyWithScalarLeavesThisColorUnchanged() throws Exception {
        Color originalColor = new Color(0.25, 0.5, 0.75);
        originalColor.multiply(Color.RED);
        assertColorEquals(new Color(0.25, 0.5, 0.75), originalColor);
    }

    @Test
    public void multiplyWithScalarLimitsValueToBeNoMoreThenOneSilently() throws Exception {
        Color color = new Color(0.25, 0.5, 0.75).multiply(10);
        assertColorEquals(Color.WHITE, color);
    }

    @Test(expected = IllegalArgumentException.class)
    public void multiplyWithNegativeScalarValueThrowsIllegalArgumentException() throws Exception {
        Color.RED.multiply(-1);
    }

    @Test
    public void addWithColorLeavesThisColorUnchanged() throws Exception {
        Color color = new Color(0.1, 0.2, 0.3);
        color.add(Color.RED);
        assertColorEquals(new Color(0.1, 0.2, 0.3), color);
    }

    @Test
    public void addWithColorLeavesPassedColorUnchanged() throws Exception {
        Color color = new Color(0.1, 0.2, 0.3);
        Color.RED.add(color);
        assertColorEquals(new Color(0.1, 0.2, 0.3), color);
    }

    @Test
    public void addWithColorRetunsNewColorWithTheSumOfEachColorComponent() throws Exception {
        Color color = new Color(0.1, 0.2, 0.3).add(new Color(0.2, 0.4, 0.6));
        assertColorEquals(new Color(0.3, 0.6, 0.9), color);
    }

    @Test
    public void addWithColorLimitsValueToBeNoMoreThenOneSilently() throws Exception {
        Color color = new Color(0.5, 0.5, 0.5).add(new Color(0.6, 0.6, 0.6));
        assertColorEquals(Color.WHITE, color);
    }

	@Test
	public void toAwtColorReturnsColorInAwtFormat() {
	    java.awt.Color awtColor = new Color(0.25, 0.5, 0.75).toAwtColor();
		assertEquals(64, awtColor.getRed());
		assertEquals(128, awtColor.getGreen());
		assertEquals(191, awtColor.getBlue());
	}
}
